package qlsl.androiddesign.api.adapter.baseadapter.listviewadapter;

import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

import qlsl.androiddesign.api.util.commonutil.Log;

/**
 * 类描述：RecyclerView适配器(未经过严格测试) onCreateViewHolder()需要重新创建布局，
 * RecyclerView和ListView调用顺序不一致：RecyclerView先调用getItemViewType onCreateViewHolder onBindViewHolder
 * 而ListView是onCreateViewHolder onBindViewHolder这个两个方法都统一到了getView里面
 * 注意事项：list_item的id和点击事件必须要放在最外层
 * 需要传入的键：recyclerView defaultItemLayoutId
 * 传入的值类型：RecyclerView int
 * 传入的值含义：从activity布局findViewById获取 item布局文件
 * 是否必传：是 否
 * 作者：郑朝军 on 2017/6/20 10:45
 * 邮箱：1250393285@qq.com
 * 公司：武汉智博创享科技有限公司
 * 修改人：郑朝军 on 2017/6/20 10:45
 * 修改备注：
 */
public abstract class RecyclerViewBaseAdapter<T> extends RecyclerView.Adapter<RecyclerViewHolder>
{
    protected List<T> list;

    protected RecyclerView mRecyclerView;

    protected Context mContext;
    /**
     * 在填充数据列表时，忽略选中状态变化
     */
    private boolean mIsIgnoreCheckedChanged = true;

    protected HeaderAndFooterAdapter mHeaderAndFooterAdapter;

    protected int mDefaultItemLayoutId;

    public RecyclerViewBaseAdapter(RecyclerView recyclerView)
    {
        mRecyclerView = recyclerView;
        mContext = mRecyclerView.getContext();
        list = new ArrayList<>();
    }

    public RecyclerViewBaseAdapter(RecyclerView recyclerView, int defaultItemLayoutId)
    {
        this(recyclerView);
        mDefaultItemLayoutId = defaultItemLayoutId;
    }

    public RecyclerViewBaseAdapter(RecyclerView recyclerView,List<T> list)
    {
        mRecyclerView = recyclerView;
        mContext = mRecyclerView.getContext();
        this.list = list;
    }

    public RecyclerViewBaseAdapter(RecyclerView recyclerView,int defaultItemLayoutId,List<T> list)
    {
        mRecyclerView = recyclerView;
        mContext = mRecyclerView.getContext();
        this.mDefaultItemLayoutId = defaultItemLayoutId;
        this.list = list;
    }

    @Override
    public int getItemViewType(int position)
    {
        if (mDefaultItemLayoutId == 0)
        {
            throw new RuntimeException("请在 " + this.getClass().getSimpleName() + " 中重写 " +
                    "getItemViewType 方法返回布局资源 id，或者使用 RecyclerViewBaseAdapter 两个参数的构造方法 " +
                    "RecyclerViewBaseAdapter(RecyclerView recyclerView, int itemLayoutId)");
        }
        return mDefaultItemLayoutId;
    }

    @Override
    public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    {
        RecyclerViewHolder viewHolder = new RecyclerViewHolder(this, mRecyclerView,
                LayoutInflater.from(mContext).inflate(viewType, parent, false));
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(RecyclerViewHolder viewHolder, int position)
    {
        // 在设置值的过程中忽略选中状态变化
        mIsIgnoreCheckedChanged = true;

        fillData(viewHolder.getmViewHolderHelper(), position, getItem(position));

        mIsIgnoreCheckedChanged = false;
    }

    @Override
    public int getItemCount()
    {
        return list.size();
    }

    public boolean isIgnoreCheckedChanged()
    {
        return mIsIgnoreCheckedChanged;
    }

    public final void notifyItemInsertedWrapper(int position)
    {
        if (mHeaderAndFooterAdapter == null)
        {
            notifyItemInserted(position);
        }
        else
        {
            mHeaderAndFooterAdapter.notifyItemInserted(mHeaderAndFooterAdapter.getHeadersCount()
                    + position);
        }
    }

    /**
     * 删除指定数据条目。该方法在 ItemTouchHelper.Callback 的 onSwiped 方法中调用
     *
     * @param viewHolder
     */
    public void removeItem(RecyclerView.ViewHolder viewHolder)
    {
        int position = viewHolder.getAdapterPosition();
        if (mHeaderAndFooterAdapter != null)
        {
            list.remove(position - mHeaderAndFooterAdapter.getHeadersCount());
            mHeaderAndFooterAdapter.notifyItemRemoved(position);
        }
        else
        {
            removeItem(position);
        }
    }

    public final void notifyItemRemovedWrapper(int position)
    {
        if (mHeaderAndFooterAdapter == null)
        {
            notifyItemRemoved(position);
        }
        else
        {
            mHeaderAndFooterAdapter.notifyItemRemoved(mHeaderAndFooterAdapter.getHeadersCount() +
                    position);
        }
    }

    public final void notifyDataSetChangedWrapper()
    {
        if (mHeaderAndFooterAdapter == null)
        {
            notifyDataSetChanged();
        }
        else
        {
            mHeaderAndFooterAdapter.notifyDataSetChanged();
        }
    }

    public final void notifyItemRangeInsertedWrapper(int positionStart, int itemCount)
    {
        if (mHeaderAndFooterAdapter == null)
        {
            notifyItemRangeInserted(positionStart, itemCount);
        }
        else
        {
            mHeaderAndFooterAdapter.notifyItemRangeInserted(mHeaderAndFooterAdapter
                    .getHeadersCount() + positionStart, itemCount);
        }
    }

    public void addHeaderView(View headerView)
    {
        getHeaderAndFooterAdapter().addHeaderView(headerView);
    }

    public void addFooterView(View footerView)
    {
        getHeaderAndFooterAdapter().addFooterView(footerView);
    }

    public HeaderAndFooterAdapter getHeaderAndFooterAdapter()
    {
        if (mHeaderAndFooterAdapter == null)
        {
            synchronized (RecyclerViewBaseAdapter.this)
            {
                if (mHeaderAndFooterAdapter == null)
                {
                    mHeaderAndFooterAdapter = new HeaderAndFooterAdapter(this);
                }
            }
        }
        return mHeaderAndFooterAdapter;
    }

    /**
     * 是否是头部或尾部
     *
     * @param viewHolder
     * @return
     */
    public boolean isHeaderOrFooter(RecyclerView.ViewHolder viewHolder)
    {
        return viewHolder.getAdapterPosition() < getHeadersCount() || viewHolder
                .getAdapterPosition() >= getHeadersCount() + getItemCount();
    }

    public int getHeadersCount()
    {
        return mHeaderAndFooterAdapter == null ? 0 : mHeaderAndFooterAdapter.getHeadersCount();
    }

    public int getFootersCount()
    {
        return mHeaderAndFooterAdapter == null ? 0 : mHeaderAndFooterAdapter.getFootersCount();
    }

    /**
     * 填充item数据
     *
     * @param helper
     * @param position
     * @param model
     */
    protected abstract void fillData(ViewHolderHelper helper, int position, T model);

    ///////////////////////////////////////////以下为提供的API
    // ///////////////////////////////////////////////////

    /**
     * 获取指定索引位置的数据模型
     *
     * @param position
     * @return
     */
    public T getItem(int position)
    {
        return list.get(position);
    }

    /**
     * 获取数据集合
     *
     * @return
     */
    public List<T> getData()
    {
        return list;
    }

    /**
     * 在集合头部添加新的数据集合
     *
     * @param data
     */
    public void addNewData(List<T> data)
    {
        if (data != null)
        {
            list.addAll(0, data);
            notifyItemRangeInsertedWrapper(0, data.size());
        }
    }

    /**
     * 在集合尾部添加更多数据集合
     *
     * @param data
     */
    public void addMoreData(List<T> data)
    {
        if (data != null)
        {
            list.addAll(list.size(), data);
            notifyItemRangeInsertedWrapper(list.size(), data.size());
        }
    }

    /**
     * 设置全新的数据集合，如果传入null，则清空数据列表（第一次从服务器加载数据，或者下拉刷新当前界面数据表）
     *
     * @param data
     */
    public void setData(List<T> data)
    {
        if (data != null)
        {
            list = data;
        }
        else
        {
            list.clear();
        }
        notifyDataSetChangedWrapper();
    }

    /**
     * 清空数据列表
     */
    public void clear()
    {
        list.clear();
        notifyDataSetChangedWrapper();
    }

    /**
     * 删除指定索引数据条目
     *
     * @param position
     */
    public void removeItem(int position)
    {
        list.remove(position);
        notifyItemRemovedWrapper(position);
    }

    /**
     * 删除指定数据条目
     *
     * @param model
     */
    public void removeItem(T model)
    {
        removeItem(list.indexOf(model));
    }


    /**
     * 在指定位置添加数据条目
     *
     * @param position
     * @param model
     */
    public void addItem(int position, T model)
    {
        list.add(position, model);
        notifyItemInsertedWrapper(position);
    }

    /**
     * 在集合头部添加数据条目
     *
     * @param model
     */
    public void addFirstItem(T model)
    {
        addItem(0, model);
    }

    /**
     * 在集合末尾添加数据条目
     *
     * @param model
     */
    public void addLastItem(T model)
    {
        addItem(list.size(), model);
    }

    public final void notifyItemChangedWrapper(int position)
    {
        if (mHeaderAndFooterAdapter == null)
        {
            notifyItemChanged(position);
        }
        else
        {
            mHeaderAndFooterAdapter.notifyItemChanged(mHeaderAndFooterAdapter.getHeadersCount() +
                    position);
        }
    }

    /**
     * 替换指定索引的数据条目
     *
     * @param location
     * @param newModel
     */
    public void setItem(int location, T newModel)
    {
        list.set(location, newModel);
        notifyItemChangedWrapper(location);
    }

    /**
     * 替换指定数据条目
     *
     * @param oldModel
     * @param newModel
     */
    public void setItem(T oldModel, T newModel)
    {
        setItem(list.indexOf(oldModel), newModel);
    }

    public final void notifyItemMovedWrapper(int fromPosition, int toPosition)
    {
        if (mHeaderAndFooterAdapter == null)
        {
            notifyItemMoved(fromPosition, toPosition);
        }
        else
        {
            mHeaderAndFooterAdapter.notifyItemMoved(mHeaderAndFooterAdapter.getHeadersCount() +
                    fromPosition, mHeaderAndFooterAdapter.getHeadersCount() + toPosition);
        }
    }

    /**
     * 移动数据条目的位置
     *
     * @param fromPosition
     * @param toPosition
     */
    public void moveItem(int fromPosition, int toPosition)
    {
        notifyItemChangedWrapper(fromPosition);
        notifyItemChangedWrapper(toPosition);

        // 要先执行上面的 notifyItemChanged,然后再执行下面的 moveItem 操作

        list.add(toPosition, list.remove(fromPosition));
        notifyItemMovedWrapper(fromPosition, toPosition);
    }

    /**
     * 移动数据条目的位置。该方法在 ItemTouchHelper.Callback 的 onMove 方法中调用
     *
     * @param from
     * @param to
     */
    public void moveItem(RecyclerView.ViewHolder from, RecyclerView.ViewHolder to)
    {
        int fromPosition = from.getAdapterPosition();
        int toPosition = to.getAdapterPosition();
        if (mHeaderAndFooterAdapter != null)
        {
            mHeaderAndFooterAdapter.notifyItemChanged(fromPosition);
            mHeaderAndFooterAdapter.notifyItemChanged(toPosition);
            // 要先执行上面的 notifyItemChanged,然后再执行下面的 moveItem 操作
            list.add(toPosition - mHeaderAndFooterAdapter.getHeadersCount(), list.remove
                    (fromPosition - mHeaderAndFooterAdapter.getHeadersCount()));
            mHeaderAndFooterAdapter.notifyItemMoved(fromPosition, toPosition);
        }
        else
        {
            moveItem(fromPosition, toPosition);
        }
    }

    /**
     * @return 获取第一个数据模型
     */
    public
    @Nullable
    T getFirstItem()
    {
        return getItemCount() > 0 ? getItem(0) : null;
    }

    /**
     * @return 获取最后一个数据模型
     */
    public
    @Nullable
    T getLastItem()
    {
        return getItemCount() > 0 ? getItem(getItemCount() - 1) : null;
    }
}
